package com.inspinia.base.util;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;

import java.awt.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created by likun on 2016/8/24 0024.
 * <p>
 * 将word文档转换成pdf文件，该类运行时需要jacob-1.18-x64.dll文件
 * 只能运行在Windows平台，而且必须要有ms office组件（office我只认微软的，目前只测试了office专业增强版2016，其他版本不保证）
 * 转换pdf的时间较长，因为word的启动速度较慢
 * 不要使用两个或多个线程调用该类的方法去打开同一个文件
 */
public class PDFUtils {
    /**
     * 日志对象
     */
    private static Logger logger = LoggerFactory.getLogger(PDFUtils.class);
    static final int wdFormatPDF = 17;// PDF 格式

    /**
     * word文档转换为pdf文档
     *
     * @param docFilePath word文档路径
     * @param pdfFilePath pdf文件的地址
     * @param text  水印文字
     * @return 如果转换成功返回pdf文件路径，否则返回null
     */
    public static String wordToPDF(String docFilePath, String pdfFilePath, String text) {
        File docPath=new File(docFilePath);
        if (!docPath.exists()){
            logger.error("文件不存在:"+docFilePath);
            return null;
        }
        try {
            String pdfFileName = getPdfFileName(docFilePath);
            if (pdfFileName != null) {
                String savaAbsolutePath = pdfFilePath + File.separator + FileUtil.randomFilename() + ".pdf";
                ActiveXComponent app = null;
                Dispatch doc = null;
                File tofile = new File(savaAbsolutePath);
                if (!tofile.getParentFile().exists()) {
                    tofile.getParentFile().mkdirs();
                }
                if (!tofile.exists()) {
                    try {
                        app = new ActiveXComponent("Word.Application");
                        app.setProperty("Visible", new Variant(false));
                        Dispatch docs = app.getProperty("Documents").toDispatch();
                        doc = Dispatch.call(docs, "Open", docFilePath).toDispatch();

                        Dispatch.call(doc,
                                "SaveAs",
                                savaAbsolutePath,
                                wdFormatPDF);
                    } catch (Exception e) {
                        e.printStackTrace();
                        try {
                            Runtime.getRuntime().exec("taskkill /f /im WINWORD.EXE");
                            logger.error("强制关闭了office进程!!!",e);
                            System.err.println("强制关闭了office进程!!!");
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                        logger.error("生成pdf文件出错,可能是文件损坏或输入了不可预测的特殊字符",e);
                        return null;
                    } finally {
                        try {
                            Dispatch.call(doc, "Close", false);
                        }catch (Exception e){
                            System.err.println("关闭office进程异常!!!");
                            logger.error("关闭office进程异常!!!",e);
                            e.printStackTrace();
                        }
                        if (app != null) {
                            app.invoke("Quit", new Variant[]{});
                        }
                        //如果没有这句话,winword.exe进程将不会关闭
                        ComThread.Release();
                    }
                    if (new File(savaAbsolutePath).exists()) {
                        String pdfPath=savaAbsolutePath.substring(0,savaAbsolutePath.lastIndexOf("."))+System.currentTimeMillis()+".pdf";
                        watermark(savaAbsolutePath, text, pdfPath);
                        File temporaryFiles=new File(savaAbsolutePath);
                        if (temporaryFiles.exists()){
                            temporaryFiles.delete();
                        }
                        savaAbsolutePath=pdfPath;
                    }
                }
                int aPublic = savaAbsolutePath.indexOf("public");
                if (aPublic != -1) {
                    pdfFileName = savaAbsolutePath.substring(aPublic);
                }
            }
            return pdfFileName;
        } catch (Throwable e) {
            logger.error("生成pdf文件出错",e);
            e.printStackTrace();
        } finally {
            ComThread.Release();
        }
        return null;
    }

    /**
     * 根据word文件绝对路径得到pdf文件路径
     *
     * @param fileName
     * @return
     */

    public static String getPdfFileName(String fileName) {
        if (fileName.lastIndexOf(".doc") != -1 || fileName.lastIndexOf(".docx") != -1
                ||fileName.lastIndexOf(".ftl") != -1 || fileName.lastIndexOf(".xml") != -1) {
            StringBuffer sb = new StringBuffer();
            int i = fileName.lastIndexOf(File.separator);
            int i1 = fileName.lastIndexOf(".");
            if (i != -1) {
                sb.append(fileName.substring(i + 1, i1));
            } else {
                sb.append(fileName.substring(0, i1));
            }
            sb.append(".pdf");
            return sb.toString();
        } else {
            logger.error("文件格式不支持:"+fileName);
            throw new IllegalArgumentException("不支持的文件类型");
        }
    }

    public static void watermark(String pdfPath,String text, String outPath){
        PdfReader pdfReader = null;
        PdfStamper pdfStamper = null;
        try {
            pdfReader = new PdfReader(pdfPath);
            pdfStamper = new PdfStamper(pdfReader, new FileOutputStream(outPath));
            addWatermark(pdfStamper, text);
        } catch (IOException e) {
            logger.error("添加水印失败",e);
            e.printStackTrace();
        } catch (DocumentException e) {
            logger.error("添加水印失败",e);
            e.printStackTrace();
        } finally {
            try {
                pdfReader.close();
                pdfStamper.close();
            } catch (DocumentException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static void addWatermark(PdfStamper pdfStamper, String waterMarkName) {
        PdfContentByte content = null;
        BaseFont base = null;
        Rectangle pageRect = null;
        PdfGState gs = new PdfGState();
        try {
            File file = ResourceUtils.getFile("classpath:doc-temp/simsun.ttc");
            // 设置字体
            base = BaseFont.createFont(file.getAbsolutePath()+",1",BaseFont.IDENTITY_H,BaseFont.EMBEDDED);
        } catch (DocumentException e) {
            logger.error("添加水印时加载字体发生错误",e);
            e.printStackTrace();
        } catch (IOException e) {
            logger.error("添加水印时加载字体发生错误",e);
            e.printStackTrace();
        }
        try {
            if (base == null || pdfStamper == null) {
                return;
            }
            // 设置透明度为0.4
            gs.setFillOpacity(0.2f);
            gs.setStrokeOpacity(0.2f);
            int toPage = pdfStamper.getReader().getNumberOfPages();
            for (int i = 1; i <= toPage; i++) {
                pageRect = pdfStamper.getReader().
                        getPageSizeWithRotation(i);
                // 计算水印X,Y坐标
                float x = pageRect.getWidth() / 2;
                float y = pageRect.getHeight() / 2;
                //获得PDF最顶层
                content = pdfStamper.getOverContent(i);
                content.saveState();
                // set Transparency
                content.setGState(gs);
                content.beginText();
                content.setColorFill(new Color(1,1,1));
                content.setFontAndSize(base, 20);
                setText(pageRect,content,waterMarkName);
                /*if (waterMarkName.length()>0){
                    // 水印文字成45度角倾斜
                    waterMarkName = waterMarkName.substring(0, waterMarkName.length()-25);
                    content.showTextAligned(Element.ALIGN_CENTER, waterMarkName, x, y, 45);
                    float x1 = pageRect.getWidth() * 0.7f;
                    float y1 = pageRect.getHeight() * 0.3f;
                    content.showTextAligned(Element.ALIGN_CENTER, waterMarkName, x1, y1, 45);
                    float x2 = pageRect.getWidth() * 0.3f;
                    float y2 = pageRect.getHeight() * 0.7f;
                    content.showTextAligned(Element.ALIGN_CENTER, waterMarkName, x2, y2, 45);
                }else{
                    setText(pageRect,content,waterMarkName);
                }*/
                content.endText();
            }
        } catch (Exception ex) {
            logger.error("设置水印出错",ex);
            ex.printStackTrace();
        } finally {
            content = null;
            base = null;
            pageRect = null;
        }
    }

    private static void setText(Rectangle pageRect, PdfContentByte content, String waterMarkName) {
        String text1="";
//        String text2="";

        if(waterMarkName.indexOf("接警处置编号")!=-1){
            text1=waterMarkName.substring(0,waterMarkName.indexOf("接警处置编号"));
            text1=text1.replace("市)",")");
        }else if (waterMarkName.indexOf("处置编号")!=-1){
            text1=waterMarkName.substring(0,waterMarkName.length()-25);
            text1=text1.replace("市)",")");
//            text2=waterMarkName.substring(waterMarkName.length()-25,waterMarkName.length());
        } else {
            text1=waterMarkName;
//            text2=waterMarkName;
            text1=text1.replace("市)",")");
        }
//        if (text2.length()>=25){
//            text2=text2.substring(0,13)+"--"+text2.substring(13,21)+"--"+text2.substring(21,25);
//        }
        float x = pageRect.getWidth() / 2;
        float y = pageRect.getHeight() / 2;
        content.showTextAligned(Element.ALIGN_CENTER, text1, x, y, 45);

        float x1 = pageRect.getWidth() * 0.7f;
        float y1 = pageRect.getHeight() * 0.3f;
        content.showTextAligned(Element.ALIGN_CENTER, text1, x1, y1, 45);

        float x2 = pageRect.getWidth() * 0.3f;
        float y2 = pageRect.getHeight() * 0.7f;
        content.showTextAligned(Element.ALIGN_CENTER, text1, x2, y2, 45);
    }
}
